package application.mvc.biz.scanner;

import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;

import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.sun.jna.ptr.IntByReference;

import application.common.constant.MessageType;
import application.common.constant.SceneType;
import application.common.model.Store;
import application.common.model.StoreUser;
import application.common.ui.ProgressStage;
import application.common.util.RouteUtil;
import application.common.util.ShiroUtil;
import application.common.util.UuidUtil;
import application.common.util.ZTScannerSDK.ZT_SCA;
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.util.Duration;

public class ScannerController implements Initializable {

	private final Log log = Log.getLog(getClass());

	@FXML
	private Label headerLabel;

	@FXML
	private Label copyrightLabel;
	
	@FXML
	private ImageView portraitImageView;
	
	@FXML
	private Label usernameLabel;
	
	@FXML
	private Label roleNameLabel;

	@FXML
	private Pane timerOutLinePane;

	@FXML
	private Pane timerInLinePane;

	@FXML
	private Label timerLabel;
	private Timeline animation;
	private RotateTransition rotateTransitionOut;
	private RotateTransition rotateTransitionIn;

	private IntByReference nHandle;

	@FXML
	private Button nextButton;

	@FXML
	private Label messageLabel;
	
	private boolean isDestroy=false;

	public void initialize(URL arg0, ResourceBundle arg1) {
		headerLabel.setText(ShiroUtil.getSoftName());
		copyrightLabel.setText(ShiroUtil.getCopyright());
		portraitImageView.setImage(ShiroUtil.getUser().getPortrait());
		usernameLabel.setText(ShiroUtil.getUser().getName());
		roleNameLabel.setText(ShiroUtil.getUser().getRoleName());
		nextButton.setVisible(ShiroUtil.isDevMode());
		message("初始化扫描仪...", true);
		new Thread(new Task<Void>() {
			@Override
			protected Void call() throws Exception {
				
				try {
					if(StrKit.isBlank(ShiroUtil.getConfig().getScannerSerialPort()) || StrKit.isBlank(ShiroUtil.getConfig().getScannerModel())) {
						throw new Exception("请配置扫描仪端口以及型号...");
					}else {
						nHandle = new IntByReference();
						nHandle.setValue(0);
						int nRet = ZT_SCA.INSTANCE.ZT_SCA_OpenDevice(
								ShiroUtil.getConfig().getScannerSerialPort(), nHandle,
								Integer.parseInt(ShiroUtil.getConfig().getScannerModel()));
						if (0 != nRet) {
							throw new Exception(String.format("开启扫描仪失败,错误码:{%s}", nRet));
						}else {
							if(0 !=  ZT_SCA.INSTANCE.ZT_SCA_Startup(nHandle.getValue())){
								throw new Exception("二维码扫描仪异常，请联系管理员！");
							}else {
								startScanner();
							}
						}
					}
					if(isDestroy) {
						destroy();
					}
				}catch (Exception e) {
					log.error("扫码页面异常",e);
					 goMessage(e.getMessage());
				}
				return null;
			}
		}).start();
	}

	public void exit(ActionEvent event) {
		if(!isDestroy) {
			isDestroy=true;
			Button bu = (Button) event.getSource();
			bu.setVisible(false);
			destroy();
			RouteUtil.goArchives();
		}
	}

	public void next(ActionEvent event) {
		if(!isDestroy) {
			isDestroy=true;
			Button bu = (Button) event.getSource();
			bu.setVisible(false);
			destroy();
			RouteUtil.goCabGroup(UuidUtil.genCode(), false);
		}
	}

	private void message(final String text, final boolean isOk) {
		Platform.runLater(new Runnable() {
			public void run() {
				if (isOk) {
					messageLabel.setId("message-label");
				} else {
					messageLabel.setId("message-label-error");
				}
				messageLabel.setText(text);
			}
		});
	}

	public void startCountDown() {
		animation = new Timeline(new KeyFrame(Duration.millis(1000), new EventHandler<ActionEvent>() {
			public void handle(ActionEvent event) {
				if(RouteUtil.getTime()>0) {
					RouteUtil.setTime(RouteUtil.getTime() - 1);
					if (RouteUtil.getTime() == 0) {
						if(!isDestroy) {
							isDestroy=true;
							timerLabel.setText("0");
							destroy();
							RouteUtil.goIndex();
						}

					} else if (RouteUtil.getTime() > 0) {
						timerLabel.setText(RouteUtil.getTime() + "");
					}
				}
				
			}
		}));
		animation.setCycleCount(Timeline.INDEFINITE);
		animation.play();
	}

	public void destroy() {
		stopScanner = true;
		if (animation != null) {
			animation.stop();
		}
		if (rotateTransitionOut != null) {
			rotateTransitionOut.stop();
		}
		if (rotateTransitionIn != null) {
			rotateTransitionIn.stop();
		}
		try {
			stopScanner = true;
			if(nHandle!=null) {
				ZT_SCA.INSTANCE.ZT_SCA_Stop(nHandle.getValue());
				ZT_SCA.INSTANCE.ZT_SCA_CloseDevice(nHandle.getValue());
			}
		}catch (Exception e) {
		}
	}


	boolean stopScanner = false;

	protected void startScanner() {
		stopScanner = false;
		Task<Void> task = new Task<Void>() {
			protected Void call() throws Exception {
				byte[] pData;
				int nRet;
				try {
					while (!stopScanner) {
						try {
							Thread.sleep(500);
						}catch (Exception e) {
						}
						pData = new byte[1024];
						nRet = ZT_SCA.INSTANCE.ZT_SCA_GetData(nHandle.getValue(), pData);
						if (0 == nRet) {
							byte[] data = byteCut(pData, 0x00);
							String scannerBarCode = new String(data);
							if(!StrKit.isBlank(scannerBarCode.trim())) {
								message("验证条码有效性...", true);
								onRead(scannerBarCode.trim());
								stopScanner = true;
								break;
							}
							continue;
						} else if (-101 != nRet) {
							throw new Exception(String.format("读取异常，错误码：{%s},可能原因{%s}", nRet, "超时、错误、串口 USB 掉线等"));
						}
					}
					if(isDestroy) {
						destroy();
					}
				}catch (Exception e) {
					log.error("扫码页面异常",e);
					goMessage(e.getMessage());
				}
				return null;
			}
		};
		Thread th = new Thread(task);
		th.setDaemon(true);
		th.start();
		message("等待条码至于扫码区域...", true);
		
		if(!isDestroy) {
			rotateTransitionOut = new RotateTransition(Duration.seconds(10), timerOutLinePane);
			rotateTransitionOut.setFromAngle(0);
			rotateTransitionOut.setToAngle(360);
			rotateTransitionOut.setByAngle(360); // 设置旋转的角度
			rotateTransitionOut.setCycleCount(Animation.INDEFINITE); // 设置旋转次数，我们需要旋转无数次
			rotateTransitionOut.setInterpolator(Interpolator.LINEAR);
			rotateTransitionOut.play();

			rotateTransitionIn = new RotateTransition(Duration.seconds(10), timerInLinePane);
			rotateTransitionIn.setFromAngle(360);
			rotateTransitionIn.setToAngle(0);
			rotateTransitionIn.setByAngle(360); // 设置旋转的角度
			rotateTransitionIn.setCycleCount(Animation.INDEFINITE); // 设置旋转次数，我们需要旋转无数次
			rotateTransitionIn.setInterpolator(Interpolator.LINEAR);
			rotateTransitionIn.play();
			startCountDown();
		}
	}

	public byte[] byteCut(byte[] bs, int cut) {
		List<Byte> list = new LinkedList<Byte>();
		for (byte b : bs) {
			list.add(b);
		}
		for (int i = list.size() - 1; i >= 0; i--) {
			if (list.get(i) == cut) {
				list.remove(i);
			} else {
				break;
			}
		}

		byte[] lastbyte = new byte[list.size()];
		for (int i = 0; i < list.size(); i++) {
			lastbyte[i] = list.get(i);
		}
		return lastbyte;
	}

	private void onRead(String barcode) {
		try {
			Store store = Store.dao.findById(barcode);
			if (store != null) {
				StoreUser storeUser = StoreUser.dao.findFirst("select * from " + StoreUser.TABLE_NAME + " where userId=? and storeId=? ",ShiroUtil.getUser().getId(), barcode);
				if (storeUser != null) {
					log.info("卷宗续存！");
					goNext( barcode);
					
				} else {
					throw new Exception("条码已占，请重新打印条码或联系条码拥有者授权！");
				}
			} else {
				log.info("新卷宗！");
				goNext(barcode);
			}
		} catch (Exception e) {
			log.error(String.format("验证条码异常:{0}", e));
			 goMessage(e.getMessage());
		}
		return;
	}
	
	private void goMessage(String message) {
		Platform.runLater(new Runnable() {
		    public void run() {
				ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
					@Override
					protected Void call() throws Exception {
						destroy();
						RouteUtil.goMessage(MessageType.ERROR,message, SceneType.SCANNER);
						return null;
					}
				},"跳转消息页面中...").show();
		    }
		});
	}
	
	
	private void goNext(String barcode) {
		Platform.runLater(new Runnable() {
			public void run() {
				if(!isDestroy) {
					isDestroy=true;
					ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
						@Override
						protected Void call() throws Exception {
							destroy();
							RouteUtil.goCabGroup(barcode, false);
							return null;
						}
					},"跳转页面中...").show();

				}
			}
		});
	}

}
